package common

import io.netty.channel.Channel
import io.netty.channel.ChannelFutureListener
import kotlinx.coroutines.experimental.channels.ActorJob
import java.util.concurrent.atomic.AtomicLong
import kotlin.coroutines.experimental.CoroutineContext

/**
 * 网络通讯channel
 * @author King
 */
class NetChannel{

    var channelId: Long = 0

    /**可能为user */
    private var cahceInfo: Any? = null

    /**是否被踢了 */
    @Volatile
    var isKick: Boolean = false
    /**是否触发心跳  true在下次心跳未收到消息将断开连接 */
    var isHeartBeat: Boolean = false

    var channel: Channel

    var actorJob: ActorJob<ITask>?=null



    constructor(channel: Channel){
        println("有一个连接进入" + channel.remoteAddress())
        val netChannel = channel.attr(ServerAttributeKey.netChannel)
        netChannel.set(this)
        val attribute = channel.attr(ServerAttributeKey.channel_Id)
        this.channelId = autoChannelId.addAndGet(1)
        attribute.set(this.channelId)
        this.channel = channel
    }

    constructor(context: CoroutineContext, channel: Channel){
        this.actorJob = kotlinx.coroutines.experimental.channels.actor(context, 1000) {
            while (true) {
                var handler = this.channel.receiveOrNull()
                if (handler === null) {
                    break
                }
                handler.run()
            }
        }
        this.channel = channel
    }


    fun write(obj: Any) {
        channel.writeAndFlush(obj)
    }

    fun writeAndClose(obj: Any) {
        channel.writeAndFlush(obj).addListener {
            ChannelFutureListener {
                it.channel().close()
            }
        }
    }


    fun call(obj: Any) {
        channel.writeAndFlush(obj)
    }


    fun <T> call(obj: Any, cls: Class<T>): T? {
        //		Response response = new Response();
        //


        //		response.waitFor();
        //		return (T)response.getBody();
        return null
    }

    fun <T : Any> getCahceInfo(): T? {
        return if (cahceInfo == null) null else cahceInfo as T?
    }

    fun setCahceInfo(cahceInfo: Any) {
        this.cahceInfo = cahceInfo
    }


    fun destory(){
        this.actorJob?.let { it.close() }
    }

    companion object {
        /**自增的id */
        private val autoChannelId = AtomicLong(0)
    }

}

